function T = calc_bit_offset(infile, outfile, varargin)
%CALC_BIT_OFFSET  按组计算表格中"bit offset"
%  假设每组内第 1 行 offset=0，后续行为之前 SIZE(BIT) 的累加。
%
%  T = calc_bit_offset('in.xlsx','out.xlsx')
%  T = calc_bit_offset(...,'GroupVar','FORMAT NAME','SizeVar','SIZE(BIT)','AltSizeVar','GENSIZE','OutVar','BIT OFFSET')
%
%  输入表必须包含：
%   - 分组列（默认 'FORMAT NAME'）
%   - 位长度列（默认 'SIZE(BIT)'；为空时可用替代列 GENSIZE）
%  输出：
%   - 将结果写入 outfile，并返回带新增列的表 T。

  p = inputParser;
  addRequired(p, 'infile',  @(s)ischar(s)||isstring(s));
  addRequired(p, 'outfile', @(s)ischar(s)||isstring(s));
  addParameter(p, 'GroupVar', 'FORMAT NAME', @(s)ischar(s)||isstring(s));
  addParameter(p, 'SizeVar',  'SIZE(BIT)',   @(s)ischar(s)||isstring(s));
  addParameter(p, 'AltSizeVar','GENSIZE',    @(s)ischar(s)||isstring(s));
  addParameter(p, 'OutVar',   'BIT OFFSET',  @(s)ischar(s)||isstring(s));
  parse(p, infile, outfile, varargin{:});
  G = string(p.Results.GroupVar);
  S = string(p.Results.SizeVar);
  A = string(p.Results.AltSizeVar);
  O = string(p.Results.OutVar);

  % 读取
  T = readtable(infile, 'Sheet', 1, 'TextType','string');

  % 尝试获取位长度（支持数字或表达式如 '8*3'）
  sz = parseBitsColumn(T, S);
  if all(isnan(sz)) && any(strcmp(T.Properties.VariableNames, A))
      sz = parseBitsColumn(T, A);
  else
      % 用替代列填补 NaN
      if any(strcmp(T.Properties.VariableNames, A))
          alt = parseBitsColumn(T, A);
          nanIdx = isnan(sz);
          sz(nanIdx) = alt(nanIdx);
      end
  end
  sz(isnan(sz)) = 0; % 空值当作 0

  % 分组并计算 offset
  if ~any(strcmp(T.Properties.VariableNames, G))
      error('未找到分组列 "%s"。', G);
  end
  [grp, ~] = findgroups(T.(G));
  % 每组内：offset = [0; cumsum(size(1:end-1))]
  offset = splitapply(@(v)[0; cumsum(v(1:end-1))], sz, grp);

  % 写回表
  if any(strcmp(T.Properties.VariableNames, O))
      T.(O) = offset;           % 覆盖已有列
  else
      T.(end+1) = table(offset, 'VariableNames', cellstr(O));
  end
  writetable(T, outfile);
  fprintf('✅ 已写出结果到 "%s"\n', outfile);

end

function v = parseBitsColumn(T, col)
% 将列解析为 double（支持数字或表达式 '8*3'、'12+4'）
  if ~any(strcmp(T.Properties.VariableNames, col))
      v = nan(height(T),1);
      return;
  end
  raw = T.(col);
  v = nan(height(T),1);
  for i = 1:height(T)
      x = raw(i);
      if isnumeric(x)
          v(i) = double(x);
      else
          s = strtrim(string(x));
          if s == "" || strcmpi(s, "NaN")
              v(i) = NaN; continue;
          end
          % 统一乘号
          s = replace(s, ["×","x","X"], "*");
          % 仅允许数字、空格、+ - * / 和括号
          if all(ismember(char(s), ['0':'9','+','-','*','/','(',')','.', ' ']))
              try
                  v(i) = eval(s); %#ok<EVLDIR> % 受控表达式
              catch
                  v(i) = str2double(s);
              end
          else
              v(i) = str2double(s);
          end
      end
  end
end
